<?php
namespace app\app\controller\v1;
use think\Db;
use think\Request;
use app\app\util\OnlineUtils;

require_once(dirname(dirname(dirname(__FILE__))).'/util/php/wxBizDataCrypt.php');
use php\WXBizDataCrypt\WXBizDataCrypt;

class AppController extends BaseController
{
	
	/**
	 * [wxlogin description]
	 * @param string code
	 * @return [type] [description]
	 */
	public function login(Request $request)
	{
		$header = $request->header();
		if($header['token'] && $header['token'] !=''){
			if(OnlineUtils::requestIsLogin()){
				$user_id = OnlineUtils::getUserIdBySid();
				$user = Db::name('users')->field('id,username,address,phone,description,portrait,wx_nick_name,sex')->where('id','eq',$id)->find();	
				return hmp(200,'success',['token'=>$header['token'],'data'=>$user]);
			}else{
				return hmp(500,'请重新登录');
			}
		}else{
			//第一次进入应用
			/**
			 * 3.小程序调用server获取token接口, 传入code, rawData, signature, encryptData.
			 */
			// $param = $request->param();
			$code = input("post.code");
			$rawData = input("post.rawData");
			$signature = input("post.signature");
			$encryptedData = input("post.encryptedData");
			$iv = input("post.iv");
			/**
			 * 4.server调用微信提供的jsoncode2session接口获取openid, session_key, 调用失败应给予客户端反馈
			 * , 微信侧返回错误则可判断为恶意请求, 可以不返回. 微信文档链接
			 * 这是一个 HTTP 接口，开发者服务器使用登录凭证 code 获取 session_key 和 openid。其中 session_key 是对用户数据进行加密签名的密钥。
			 * 为了自身应用安全，session_key 不应该在网络上传输。
			 * 接口地址："https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code"
			 */
			$params = [
				'appid' => CONFIG('APPID'),
				'secret' => CONFIG('SECRET'),
				'js_code' => $code,
				'grant_type' => 'authorization_code'
			];
			$url = "https://api.weixin.qq.com/sns/jscode2session";
			$res = makeRequest($url, $params);
			//result是否存在
			$reqData = json_decode($res);

			if (!isset($reqData->session_key)) {
				return hmp('202','未知错误2');
			}
			$sessionKey = $reqData->session_key;

			/**
			 * 5.server计算signature, 并与小程序传入的signature比较, 校验signature的合法性, 不匹配则返回signature不匹配的错误. 不匹配的场景可判断为恶意请求, 可以不返回.
			 * 通过调用接口（如 wx.getUserInfo）获取敏感数据时，接口会同时返回 rawData、signature，其中 signature = sha1( rawData + session_key )
			 *
			 * 将 signature、rawData、以及用户登录态发送给开发者服务器，开发者在数据库中找到该用户对应的 session-key
			 * ，使用相同的算法计算出签名 signature2 ，比对 signature 与 signature2 即可校验数据的可信度。
			 */
			$signature2 = sha1($rawData . $sessionKey);

			if ($signature2 != $signature) return hmp('202','签名错误');

			/**
			 *
			 * 6.使用第4步返回的session_key解密encryptData, 将解得的信息与rawData中信息进行比较, 需要完全匹配,
			 * 解得的信息中也包括openid, 也需要与第4步返回的openid匹配. 解密失败或不匹配应该返回客户相应错误.
			 * （使用官方提供的方法即可）
			 */
			$pc = new WXBizDataCrypt(config('APPID'), $sessionKey);
			$errCode = $pc->decryptData($encryptedData, $iv, $data );

			if ($errCode !== 0) {
				return hmp('202','验证失败');
			}
			$data = json_decode($data);
			//验证通过
			// $unionid = $data['unionid'];
			$openid = $data->openId;
			//获取登录状态，生成登录码
			$encode_code = base64_encode($openid);
			$access_key  = randomFromDev(100,$encode_code);
			//查询用户是否存在
			$user = Db::name('users')->field('id,username,address,phone,description,portrait,wx_nick_name,sex')->where('wx_openid','eq',$openid)->where('status','eq',1)->find();
			if($user){
				$token = md5(time().$user['id']);
				OnlineUtils::sidLogin($token,$user);
				return hmp(200,'success',['token'=>$token,'data'=>$user]); 
			}else{
				// 注册加登录
				$arr = array('wx_openid'=>$openid,'wx_nick_name'=>$data->nickName,'portrait'=>$data->avatarUrl,'sex'=>$data->gender);
				$city     = $data->city;
				$province = $data->province;
				$country  = $data->country;
				$arr['address'] = $country.$province.$city;			
				//如果有邀请码
				if(input('post.invite_code') && input('post.invite_code') !=''){
					$invite_user = Db::name('users')->where('invite_code','eq',input('invite_code'))->find();
					if($invite_code){
						$commission = Db::name('sys_options')->where('option_key','eq','commission')->find();
						Db::query('update hmp_users set commission = commission + '.$commission['option_value'].' where id ='.$invite_user['id']);
					}
				}
				//生成邀请码
				$code = intval(substr($openid,9,2)) + time()/26;
				$arr['invite_code'] = codeChange($code);
				$arr['register_time'] = date('Y-m-d H:i:s',time());
				$id  = Db::name('users')->insertGetId($arr);
				$user = Db::name('users')->field('id,username,address,phone,description,portrait,wx_nick_name,sex')->where('id','eq',$id)->find();
				//登录
				$token = md5(time().$id);
				OnlineUtils::sidLogin($token,$user);
				return hmp(200,'success',['token'=>$token,'data'=>$user]);
			}	
		}
	}

	public function wxCheck()
	{
    	$signature =  input("get.signature");
        $timestamp =  input("get.timestamp");
    	$nonce     =  input('get.nonce');
    	$token     =  config('WX_TOKEN');
    	$echostr   =  input('get.echostr');
    	$arr       = array($timestamp,$nonce,$token);
    	sort($arr,SORT_STRING);
		$tmpStr    = implode($arr );
		$tmpStr    = sha1( $tmpStr );
		//验证
		if( $signature == $tmpStr ){
			header('content-type:text');
			echo $echostr;
		}else{
			return false;
		}		
	}	
	
	public function test()
	{
		$id = input('get.id');
		$token = md5(time().$id);
		$user = Db::name('users')->field('id,username,wx_openid,address,phone,description,portrait,wx_nick_name,sex')->where('id','eq',$id)->where('status','eq',1)->find();
		OnlineUtils::sidLogin($token,$user);
		return hmp(200,'success',['token'=>$token,'data'=>$user]); 
	}
	
}